/** @file    FormBusViewer.cpp
 *  @author  Alessandro Polo
 *  @version $Id: FormBusViewer.cpp 2253 2010-03-29 11:58:04Z alex $
 *  @brief
 * File containing methods for the wosh::gui::FormBusViewer class.
 * The header for this class can be found in FormBusViewer.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include "FormBusViewer.h"
 #include "ui_FormBusViewer.h"

// #include <core/ObjectAllocator.h>

using namespace std;
namespace wosh {
 namespace gui {

// WOSH_REGISTER(wosh::gui::FormBusViewer, "wosh::gui::IWidgetGeneric", 1.0, _static_FormBusViewer )

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

FormBusViewer::FormBusViewer(QWidget *parent) : QWidget(parent), IBusListener()
 {
	this->m_ui = new Ui::FormBusViewer();
	this->m_ui->setupUi(this);

	this->setWindowTitle("Bus Viewer");
	QIcon icon; icon.addPixmap(QPixmap(QString::fromUtf8(":/icons/var/extras/icons/wosh.Bus.png")), QIcon::Normal, QIcon::Off);
	this->setWindowIcon(icon);

	// tab Messages [0]
	this->menuColumns = new QMenu(this);
	this->m_ui->tBtnColumnSelection->setMenu(this->menuColumns); 
	connect(this->menuColumns, SIGNAL(triggered(QAction*)), this, SLOT(menuColumns_triggered(QAction*)));
	changeModel( new MessageTableModel(this->messageCache, this) );
	connect(this->m_ui->tableView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(tableView_doubleClicked(const QModelIndex&)));

	// create column menu from TABLE MODEL: for each column in getcols(): new qaction, checked, save int as setData (user)
	// on click, update tableview settings

	// tab Configuration [1]
	this->messageCacheMax = 50;
	this->m_ui->spinMessagesMax->setValue(this->messageCacheMax);

	this->m_ui->uriSelFilterSourceURI->getTargetURI().clear();
	this->m_ui->uriSelFilterDestinationURI->getTargetURI().clear();

	connect(this->m_ui->listFilterSourceBus, SIGNAL(currentRowChanged(int)), this, SLOT(event_filter_sourcebus(int)));
	connect(this->m_ui->listFilterDestinationBus, SIGNAL(currentRowChanged(int)), this, SLOT(event_filter_destinationbus(int)));
	connect(this->m_ui->chkFilterContentEmpty, SIGNAL(stateChanged(int)), this, SLOT(event_filter_contentEmpty(int)));
	connect(this->m_ui->uriSelFilterSourceURI, SIGNAL(changedURI(const URI&)), this, SLOT(event_filter_source(const URI&)));
	connect(this->m_ui->uriSelFilterDestinationURI, SIGNAL(changedURI(const URI&)), this, SLOT(event_filter_destination(const URI&)));
	connect(this->m_ui->spinMessagesMax, SIGNAL(valueChanged(int)), this, SLOT(event_message_max(int)));

	// register to BUS
	BusGui.setMessageHandler(this);
	WRESULT bus_connected = BusGui.connect( _Bus_Gui );
	(void)bus_connected;
 }

FormBusViewer::~FormBusViewer() {
	delete this->m_ui;
 }

void FormBusViewer::changeEvent(QEvent *e) {
	QWidget::changeEvent(e);
	if ( e->type() == QEvent::LanguageChange )
		this->m_ui->retranslateUi(this);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::changeModel(MessageTableModel* model) {
	this->wTableModel = model;
	this->m_ui->tableView->setModel(this->wTableModel);
	if ( this->wTableModel == NULL ) return;

	this->menuColumns->actions().clear();
	for(int i=0; i<this->wTableModel->columnCount(); ++i) {
		QAction* action = this->menuColumns->addAction( this->wTableModel->headerData(i, Qt::Horizontal).toString() );
		action->setData( i );
		action->setCheckable(true);
		action->setChecked(true);
	 }
 }

void FormBusViewer::event_message_max( int value ) {
	MutexLockerWrite mL(this->messageCache.getMutex());
	this->messageCacheMax = value;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::menuColumns_triggered( QAction* action ) {
	if ( action == NULL ) return;
	if ( action->isChecked() )
		this->m_ui->tableView->showColumn(action->data().toInt());
	else
		this->m_ui->tableView->hideColumn(action->data().toInt());
 }

void FormBusViewer::tableView_doubleClicked( const QModelIndex& index ) {
	if ( !index.isValid() || index.internalPointer() == NULL ) return;
	Message* message = reinterpret_cast<Message*>(index.internalPointer());
	if ( message ==NULL ) return;

//	Message* message_copy = message->clone();
	// Open MessageWidget!
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::busMessage( const Message& message, const Bus* source ) {

	// DO FILTER

	this->messageCache.transactionBeginWrite();
	if ( this->messageCache.size() >= this->messageCacheMax )
		this->messageCache.erase(this->messageCache.begin(), true);
	this->messageCache.push_back(message.clone());
	this->messageCache.transactionEnd();

	this->wTableModel->reset();
	this->m_ui->tableView->resizeColumnsToContents();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::event_filter_sourcebus( int row ) {
	if ( row == -1 || row == 0 )
		this->filterSourceBus = "";
	else
		this->filterSourceBus = this->m_ui->listFilterSourceBus->currentItem()->text().toStdString();
 }

void FormBusViewer::event_filter_destinationbus( int row ) {
	if ( row == -1 || row == 0 )
		this->filterDestinationBus = "";
	else
		this->filterDestinationBus = this->m_ui->listFilterDestinationBus->currentItem()->text().toStdString();
 }

void FormBusViewer::event_filter_source( const URI& uri ) {
	this->filterSourceURI = !uri.isEmpty();
 }

void FormBusViewer::event_filter_destination( const URI& uri ) {
	this->filterDestinationURI = !uri.isEmpty();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::refreshAll()
 {
	//this->m_ui->listFilterSourceBus
	//this->m_ui->listFilterDestinationBus
//uriSelFilterSourceURI
//uriSelFilterDestinationURI
//cmbFilterContentType
//chkFilterContentEmpty

 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
bool FormBusViewer::filterMessage( const Message& message, const Bus* source )
 {
	(void)source;

	// filter message content
	if ( message.isEmpty() ) {
		if ( this->filterContentEmpty )
			return false;
	 }
	else if ( this->filterContentType != MessageContent::GENERIC ) {
		if ( this->filterContentType != message.getContent()->getType() )
			return false;
	 }

	// filter source BUS
	if ( !this->filterSourceBus.empty() && this->filterSourceBus != _Bus_ANY ) {
		if ( this->filterSourceBus != message.getSourceBus() )
			return false;
	 }

	// filter destination BUS
	if ( !this->filterDestinationBus.empty() && this->filterDestinationBus != _Bus_ANY ) {
		if ( this->filterDestinationBus != message.getDestinationBus() )
			return false;
	 }

	// filter source URI
	if ( this->filterSourceURI ) {
		if ( !URI::pregMatch( this->m_ui->uriSelFilterDestinationURI->getTargetURI(), message.getSource() ) )
			return false;
	 }
	// filter destination URI
	if ( this->filterDestinationURI ) {
		if ( !URI::pregMatch( this->m_ui->uriSelFilterDestinationURI->getTargetURI(), message.getDestination() ) )
			return false;
	 }


	return true;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormBusViewer::busMessage( const Message& message, const Bus* source )
 {
	if ( !filterMessage(message, source) )
		return;


	this->m_ui->tblMessages->insertRow(0);
	if ( this->messageCacheMax < this->m_ui->tblMessages->rowCount() ) {
		this->m_ui->tblMessages->removeRow(this->m_ui->tblMessages->rowCount()-1);
	 }

	int row = 0;
	int col = 0;

	QTableWidgetItem* twi_id = new QTableWidgetItem( QString::number(message.getID())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_id);

	QTableWidgetItem* twi_rid = new QTableWidgetItem( QString::number(message.getReferenceID())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_rid);

	QTableWidgetItem* twi_sbus = new QTableWidgetItem( QString(message.getSourceBus().c_str())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_sbus);

	QTableWidgetItem* twi_suri = new QTableWidgetItem( QString(message.getSource().toString().c_str())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_suri);

	QTableWidgetItem* twi_tbus = new QTableWidgetItem( QString(message.getDestinationBus().c_str())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_tbus);

	QTableWidgetItem* twi_turi = new QTableWidgetItem( QString(message.getDestination().toString().c_str())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_turi);

	QTableWidgetItem* twi_type = new QTableWidgetItem( QString(message.getContentClassName().c_str())  );
	this->m_ui->tblMessages->setItem(row, col++, twi_type);

	this->m_ui->tblMessages->resizeColumnsToContents();
 }
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace gui
}; // namespace wosh
